import Guide from '~/components/layout/guide'
import { InlineCode } from '~/components/text/code'
import Snippet from '~/components/snippet'
import Caption from '~/components/text/caption'
import Note from '~/components/text/note'
import DeploySection from '~/components/guides/deploy-section'

export const meta = {
  title: 'Deploying with Custom Serverless Next.js Routing',
  description:
    'Migrate from a Next.js app with a custom server to a serverless Next.js app using ZEIT Now routes.',
  published: '2019-01-23T17:00:00.860Z',
  authors: ['timothy', 'timneutkens'],
  name: 'Next.js',
  type: 'app',
  url: '/guides/custom-next-js-server-to-routes',
  editUrl: 'pages/guides/custom-next-js-server-to-routes.mdx',
  lastEdited: '2020-02-04T12:49:00.000Z'
}

Next.js offers developers [a built-in routing system](https://nextjs.org/docs/#routing) that allows you to link to other pages whilst also giving those pages a custom URL. When a user refreshes the custom URL, however, the browser will not be able to load the link because the page was previously routed client-side. To resolve this, we need to also handle routing server-side.

<Note type="warning">This guide requires Next.js 9+ to work correctly.</Note>

## Preface: Next.js Routing

When you [link to a page](https://nextjs.org/docs/#routing) within the same Next.js app, you can provide two options. The first and required option is `href`. This is a link to the page as it exists in the `pages` directory. The second is `as` which describes the URL Next.js should show when routing to that page.

For example, if you have a page located at `pages/product.js` in your codebase, you can use the `href` option with the value `/product?name=<product_name>` to route and render that page with a query parameter, however, if you want to show the URL `/product/<product_name>`, you can use the `as` option to format the URL when routing.

This is an amazing feature of Next.js, however, it cannot control how the server routes to the app if the routes are not defined with the server.

### The Old Custom Server Method

The solution to this problem was previously using a custom server. For example, you could create an Express app, catch the request to `/product/<product_name>` and route it to the `/product?name=<product_name>` file behind the scenes so that you can keep the custom URL:

```js
server.get('/products/:name', (req, res) => {
  return app.render(req, res, '/product', { name: req.params.name })
})
```

<Caption>An example custom server route capture and render method.</Caption>

<Note type="warning">
  The custom server method will not work with the ZEIT Now 2.0 platform.
</Note>

### The New Routes Method

With [ZEIT Now](https://zeit.co/now) and the serverless approach, each [Next.js page](https://nextjs.org/docs#routing) is a separate entry point, making the sole custom server entry point a thing of the past for the good of performance and stability. Fortunately, **ZEIT Now 2.0 offers a solution**, handling the configuration of routes for you.

By making use of Next.js path segments with ZEIT Now, [dynamic routing](https://nextjs.org/docs#routing) is achieved through the file structure. No longer are custom servers or additional configuration required, **simplifying the process of building your app significantly**.

## By Example

If you are yet to set up routing for [your Next.js app](https://nextjs.org/docs/#setup), this brief example describes how to use Next.js routing with [ZEIT Now](https://zeit.co/now) to support custom URLs.

### Step 1: Defining Pages

The first part of creating defined routes is to make sure those routes can be rendered as pages. In this example, we will have two pages, "index" (our homepage) and "product".

The `index.js` inside of our `pages` directory is just a small page that exports a heading and a paragraph of text with a link to our future products page using a [Next.js Link component](https://nextjs.org/docs/#with-link):

```jsx
import Link from 'next/link'

export default () => (
  <div>
    <h1>Welcome to our Next.js website!</h1>
    <p>
      View our{' '}
      <Link href="/product/espresso">
        <a>espresso product</a>
      </Link>
      !
    </p>
  </div>
)
```

<Caption>
  An example <InlineCode>index.js</InlineCode> file for our project.
</Caption>

<Note>
  In a real app, the product name query parameter would most likely be dynamic
  based on other factors, but for simplicity, we'll use "espresso" as the
  product name.
</Note>

Next, for our link to work, we need to create a `/product` directory inside of `/pages`, then a `[name].js` file inside of `/product`. This page displays the query parameter, which we receive with the [Next.js `getInitialProps` lifecycle method](https://nextjs.org/docs/#fetching-data-and-component-lifecycle), as the title and a simple paragraph:

```jsx
const Product = ({ name }) => (
  <div>
    <h1>{name}</h1>
    <p>Welcome to our product page for {name}!</p>
  </div>
)

Product.getInitialProps = async ({ query }) => {
  return { name: query.name }
}

export default Product
```

<Caption>
  An example <InlineCode>[name].js</InlineCode> file for our project.
</Caption>

Now, clicking the espresso product link will result in the URL path being `/product/espresso` while rendering the `product` page with the name query parameter set to `espresso`.

### Step 2: Deploying

<DeploySection meta={meta} />

export default ({ children }) => <Guide meta={meta}>{children}</Guide>

export const config = {
  amp: 'hybrid'
}
